#include "CommandConsole.h"

namespace mp_base { namespace console {

	const string CommandConsole::CMD_CONSOLE_PREFIX = "} ";
	const string CommandConsole::CMD_CONSOLE_ERROR_PREFIX = "Cmd Error} ";
	const string CommandConsole::CMD_NOT_FOUND_ERROR = "Command not found!";


	void CommandConsole::RegisterCommandListener(spCommandListener cmd)
	{
		//Locate the command if possible
		hmCommandListeners::const_iterator il;
		il = m_listeners.find(cmd->GetCommand());
		//If already exists, return
		if (il == m_listeners.end()) return;
		//Register listener in the hash map
		m_listeners.insert(hmCommandListener(cmd->GetCommand(), cmd));

	}

	void CommandConsole::RemoveCommandListener(spCommandListener cmd)
	{
		//Locate the command if possible
		hmCommandListeners::const_iterator il;
		il = m_listeners.find(cmd->GetCommand());
		//If does not exist, return
		if (il == m_listeners.end()) return;
		//Remove listener from the hash map
		m_listeners.erase(il);
	}

	bool CommandConsole::SendCommand(const string cmd){
		//Write attempted cmd
		cout << "\n"
			 << CMD_CONSOLE_PREFIX
			 << cmd;
		//Create new command in a shared pointer
		Command* tmp = NULL;
		spCommand sCmd; 
		sCmd.reset();
		try
		{
			//Separate command from arguments
			int firstIndex = cmd.find_first_of(" ");
			string cmds = cmd.substr(0, firstIndex);
			string args = cmd.substr(firstIndex, cmd.length() - 1);
			//Create Command Object
			tmp = new Command(cmds, args);
			//Push the Command Object into a Shared Pointer
			sCmd.reset(tmp);
		}
		catch (string e)
		{
			//Om failure to create a new command
			tmp = NULL;
			sCmd.reset();
			cout << "\n"
				 << CMD_CONSOLE_ERROR_PREFIX
				 << e;
			return false;
		}
		//Add the command to the buffer
		m_inputBuffer.push_back(sCmd);
		//Process the command with the listeners
		return ProcessCommand(sCmd);
	}

	bool CommandConsole::SendCommand(const char* cmd){
		return SendCommand(string(cmd));}

	bool CommandConsole::SendCommand(spCommand cmd){
		std::cout << cmd->GetEventMessage();
		m_inputBuffer.push_back(cmd);
		return ProcessCommand(cmd);
	}

	// -- Private --

	bool CommandConsole::ProcessCommand(spCommand& cmd)
	{
		//Locate the command if possible
		hmCommandListeners::iterator il;
		il = m_listeners.find(cmd->GetCommand());
		//If does not exist, return
		if (il == m_listeners.end())
		{
			cout << "\n"
				 << CMD_CONSOLE_ERROR_PREFIX
				 << CMD_NOT_FOUND_ERROR;
			return false;
		}
		//Send command to the listener
		(((*il).second)->GetListenerFcn())(*cmd);

		return true;
	}

}}